package cn.epsilon3.configuration;

import cn.epsilon3.common.E3BaseService;
import cn.epsilon3.configBean.InitializingSecurityBlackListConfig;
import cn.epsilon3.constant.E3CacheKeyEnum;
import cn.epsilon3.domain.e3.po.E3BlackIpPo;
import cn.epsilon3.domain.e3.po.E3UrlPO;
import cn.epsilon3.mybatis.mapper.E3BlackIpMapper;
import cn.epsilon3.mybatis.mapper.E3UrlMapper;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import net.jodah.expiringmap.ExpiringMap;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description 安全组件自动配置
 *
 * @author: epsilon3
 * @date: 2023/12/6 9:48
 */
@Configuration
public class E3SecurityConfiguration extends E3BaseService {

    private static final Log log = LogFactory.get();

    @Resource
    private E3UrlMapper e3UrlMapper;

    @Resource
    private E3BlackIpMapper blackIpMapper;

    @Resource
    private InitializingSecurityBlackListConfig blackListConfig;

    /**
     * 初始化可达路径
     *
     * @return map key为路径URL，value为是否有效
     */
    private ConcurrentHashMap<String,Integer> loadUrl() {
        log.info("---------------------开始加载可达路径---------------------");
        ConcurrentHashMap<String, Integer> concurrentHashMap = initConcurrentHashMap(String.class, Integer.class);
        List<E3UrlPO> e3UrlPOS = e3UrlMapper.selectList(queryWrappers(E3UrlPO.class));
        if (CollectionUtil.isNotEmpty(e3UrlPOS)) {
            e3UrlPOS.forEach((url) -> {
                concurrentHashMap.put(url.getUrl(),url.getEffective());
                log.info("---------------------已加载：{}---------------------",url.getUrl());
            });
        }
        log.info("---------------------加载可达路径完成---------------------");
        return concurrentHashMap;
    }

    /**
     * 启动时加载可达路径
     *
     * @return 可达路径缓存
     */
    @Bean("loadUrlCache")
    @DependsOn("e3UrlMapper")
    @SuppressWarnings("unchecked")
    public ConcurrentHashMap<String,Integer> loadUrlCache() {
        return (ConcurrentHashMap<String,Integer>) initCaffeineCache().get(E3CacheKeyEnum.URL.getKey(), (k) ->
                loadUrl());
    }


    /**
     * 初始化加载数据库黑名单
     *
     * @return map key为黑名单ip，value为配置的最大访问次数
     */
    private ExpiringMap<String,Integer> loadBlackIp() {
        ExpiringMap<String, Integer> expiringMap = initExpiringMap(String.class, Integer.class);
        if (blackListConfig.getEnable()) {
            log.info("---------------------开始加载黑名单进缓存---------------------");
            List<E3BlackIpPo> e3BlackIpPos = blackIpMapper.selectList(queryWrappers(E3BlackIpPo.class));
            List<String> defaultIp = blackListConfig.getDefaultIp();
            if (CollectionUtil.isEmpty(e3BlackIpPos) && CollectionUtil.isEmpty(defaultIp)) {
                log.info("---------------------加载黑名单进缓存完成，共加载：0个---------------------");
                return expiringMap;
            }
            if (CollectionUtil.isNotEmpty(defaultIp)) {
                defaultIp.forEach((ip) -> {
                    expiringMap.put(ip + E3CacheKeyEnum.BLACK_IP.getKey(), blackListConfig.getCount());
                    log.info("---------------------已加载默认ip：{}---------------------",ip);
                });
            }
            if (CollectionUtil.isNotEmpty(e3BlackIpPos)) {
                e3BlackIpPos.forEach((ip) -> {
                    expiringMap.put(ip.getIp() + E3CacheKeyEnum.BLACK_IP.getKey(), blackListConfig.getCount());
                    log.info("---------------------已加载ip：{}---------------------",ip.getIp());
                });
            }
            log.info("---------------------加载黑名单进缓存完成，共加载：{}个---------------------", expiringMap.size());
        }
        return expiringMap;
    }


    /**
     * 启动时加载黑名单ip
     *
     * @return 黑名单ip缓存
     */
    @Bean("loadBlackIpCache")
    @DependsOn("e3BlackIpMapper")
    @SuppressWarnings("unchecked")
    public  ExpiringMap<String, Integer> loadBlackIpCache() {
        return ( ExpiringMap<String, Integer>) initCaffeineCache().get(E3CacheKeyEnum.BLACK_IP.getKey(), (k) ->
                loadBlackIp());
    }
}
